﻿package smooth.core.object.googleMapCanvasComponent {
	import app.core.action.RotatableScalableChangedEvent;
	import caurina.transitions.Tweener;
	import com.google.maps.LatLng;
	import com.google.maps.LatLngBounds;
	import flash.display.DisplayObject;
	import flash.display.Shape;
	import flash.geom.Point;
	import flash.filters.*;
	import flash.events.*;
	import flash.utils.Timer;
	import flash.events.TimerEvent;
	import smooth.core.canvas.liquidCanvas.LiquidCanvas;
	import smooth.core.object.googleMapLayerComponent.GoogleMapLayerComponent;
	import smooth.core.object.interactiveLocalizationComponent.InteractiveLocalizationComponent;
	import smooth.core.object.interactiveTextComponent.InteractiveTextComponent;
	import smooth.core.object.localizationComponent.LocalizationComponent;
	import smooth.core.object.googleMapComponent.GoogleMapsPureASComponent;
	import smooth.core.object.googleMapComponent.TappableMap;
	import smooth.core.object.googleMapComponent.MapChangedEvent;
	import smooth.core.object.menuButtonComponent.MenuButtonChangedStateEvent;
	import smooth.core.object.menuButtonComponent.MenuButtonComponent;
	
	
	public class GoogleMapCanvasComponent extends LiquidCanvas {	
		
		private static const CANVAS_BORDER_WIDTH:int = 40;
		
		private var googleMapObject:GoogleMapsPureASComponent;
		// START - 20081126 - LSA
		//private var menuMap:GoogleMapCanvasMenu;
		// END - 20081126 - LSA
		private var normalMapLayer1:GoogleMapLayerComponent;
		private var hybridMapLayer1:GoogleMapLayerComponent;
		private var physicalMapLayer1:GoogleMapLayerComponent;
		private var initialWidth:int;
		private var initialHeight:int;
		private var initialPosX:int;
		private var initialPosY:int;
		private var initialColor:int;
		// START - 20081126 - LSA
		//private var lastAddressSearched:InteractiveTextComponent;
		private var lastAddressSearched:Object;
		// END - 20081126 - LSA
		
		public function GoogleMapCanvasComponent(posX:int, posY:int, sizeX:int, sizeY:int, color:int)	{
			// Init des attributs de l'objet
			this.initialPosX = posX;
			this.initialPosY = posY;
			this.initialWidth = sizeX;
			this.initialHeight = sizeY;
			this.initialColor = color;
			// Constructeur parent
			super(posX, posY, sizeX, sizeY, color);
			// Init des visuels du composant			
			initGraphics();
			// Init des events du composant
			initEvents();	
			// Init des process du composant
			initProcess();
			// START - 20081116 - LSA
			//this.noRotate = true;
			// END - 20081116 - LSA
		}	
		
		private function initGraphics():void {
			this.graphics.lineStyle(0,0x000000, 0);
			this.graphics.beginFill(0x000000, 0);
			this.graphics.drawRoundRect(0, 0, this.initialWidth, this.initialHeight, 20, 20);
			this.graphics.endFill();
			this.width = this.initialWidth;
			this.height = this.initialHeight;
		}
		
		private function initProcess():void {
			this.googleMapObject = new GoogleMapsPureASComponent(CANVAS_BORDER_WIDTH, CANVAS_BORDER_WIDTH, this.initialWidth-2*CANVAS_BORDER_WIDTH, this.initialHeight-2*CANVAS_BORDER_WIDTH);
			this.addChildAt(this.googleMapObject, this.numChildren);
			// START - 20081126 - LSA
			//this.menuMap = new GoogleMapCanvasMenu(this.initialWidth, 0, this.initialColor);
			//this.addChild(this.menuMap);
			this.removeChild(this.menu);
			this.menu = new GoogleMapCanvasMenu(this.width-25, 25, 0x00FF00, 160);
			this.menu.visible = false;
			this.menu.scaleX = 0.5;
			this.menu.scaleY = 0.5;
			this.addChild(this.menu);
			// Add layers buttons to menu
			this.menu.addButton(new NormalMapButtonComponent(this));
			this.menu.addButton(new HybridMapButtonComponent(this));
			this.menu.addButton(new PhysicalMapButtonComponent(this));
			// Add menu button component
			this.removeChild(this.menuButton);
			this.menuButton = new MenuButtonComponent(this, this.initialWidth - 25, 25, 40, 40, 0xFFFFFF, 0.7);
			this.menuButton.addEventListener(MenuButtonChangedStateEvent.menuButtonChangedState, this.showHideMenu);
			this.addChild(this.menuButton);
			// END - 20081126 - LSA
		}
		
		private function initEvents():void {
			this.addEventListener(MapChangedEvent.mapChanged, refreshLayers, true, 0, true);
			this.addEventListener(RotatableScalableChangedEvent.rotateScaled, refreshLayersAfterRotateScaled);
		}
		
		public function getZoom():Number {
			return this.googleMapObject.getZoom();
		}
		
		public function getMap():TappableMap {
			return this.googleMapObject.getMap();
		}
		
		public function globalToLocalMap(point:Point):Point {
			return this.googleMapObject.globalToLocalMap(point);
		}
		
		public function fromViewportToLatLng(point:Point):LatLng {
			return this.googleMapObject.fromViewportToLatLng(point);
		}
		
		// START - 20081126 - LSA
		//public function geocodeService(search:InteractiveTextComponent):void {
		public function geocodeService(search:Object):void {
			if (search is InteractiveTextComponent) {
		// END - 20081126 - LSA
				var address:String = search.getText();
				if (address != "") {
					this.lastAddressSearched = search;
					if (googleMapObject.getStatus() == GoogleMapsPureASComponent.MAP_STATUS_READY) {
						this.googleMapObject.doGeocodeAddress(address);
					} else {
						alarmTimer =new Timer(2,1);
						alarmTimer.addEventListener(TimerEvent.TIMER, tryAgainGeocodeService);
						alarmTimer.start();
					}
				}
		// START - 20081126 - LSA
			}
		// END - 20081126 - LSA
		}
		
		private function tryAgainGeocodeService(e:TimerEvent):void {
			geocodeService(this.lastAddressSearched);
		}
		
		// START - 20081126 - LSA
		public function addMarkerService(localizationObject:Object):void {
			if (localizationObject is InteractiveLocalizationComponent) {
				this.lastAddressSearched = localizationObject;
				if (googleMapObject.getStatus() == GoogleMapsPureASComponent.MAP_STATUS_READY) {
					var lat:Number = localizationObject.getLat();
					var lng:Number = localizationObject.getLng();
					var text:Number = localizationObject.getText();
					this.googleMapObject.doAddMarker(lat, lng, text);
				} else {
					alarmTimer =new Timer(2,1);
					alarmTimer.addEventListener(TimerEvent.TIMER, tryAgainAddMarkerService);
					alarmTimer.start();
				}
			}
		}
		
		private function tryAgainAddMarkerService(e:TimerEvent):void {
			addMarkerService(this.lastAddressSearched);
		}
		// END - 20081126 - LSA
		
		public function doCreateMarker(point:Point, lat:Number, lng:Number, container:DisplayObject):void {
			var label:String = "Lat:" + lat + " / Long:" + lng;
			var localContainer:TappableMap = container as TappableMap;
			var localization1:LocalizationComponent = new LocalizationComponent(container.localToGlobal(point), lat, lng, label);
			this.stage.addChild(localization1);
		}
		
		public function doDisplayNormalMapLayer(color:int):void {
			var layerWidth:int = this.initialWidth / 2;
			var layerHeight:int = this.initialHeight / 2;
			var layerX:int = (this.initialWidth-layerWidth)/2;
			var layerY:int = (this.initialHeight-layerHeight)/2;
			this.normalMapLayer1 = new GoogleMapLayerComponent(layerX, layerY, layerWidth, layerHeight, color, GoogleMapLayerComponent.NORMAL_MAP_TYPE, this.googleMapObject.getCenter(), this.googleMapObject.getZoom());
			this.addChild(normalMapLayer1);
		}
		
		public function doCloseNormalMapLayer():void {
			trace("doCloseNormalMapLayer");
			this.removeChild(this.normalMapLayer1);
			this.normalMapLayer1 = null;
		}
		
		public function getNormalMapLayer():GoogleMapLayerComponent {
			return this.normalMapLayer1;
		}
		
		public function doDisplayHybridMapLayer(color:int):void {
			var layerWidth:int = this.initialWidth / 2;
			var layerHeight:int = this.initialHeight / 2;
			var layerX:int = (this.initialWidth-layerWidth)/2;
			var layerY:int = (this.initialHeight - layerHeight) / 2;
			this.hybridMapLayer1 = new GoogleMapLayerComponent(layerX, layerY, layerWidth, layerHeight, color, GoogleMapLayerComponent.HYBRID_MAP_TYPE, this.googleMapObject.getCenter(), this.googleMapObject.getZoom());
			this.addChild(hybridMapLayer1);
		}
		
		public function doCloseHybridMapLayer():void {
			this.removeChild(this.hybridMapLayer1);
			this.hybridMapLayer1 = null;
		}
		
		public function getHybridMapLayer():GoogleMapLayerComponent {
			return this.hybridMapLayer1;
		}
		
		public function doDisplayPhysicalMapLayer(color:int):void {
			var layerWidth:int = this.initialWidth / 2;
			var layerHeight:int = this.initialHeight / 2;
			var layerX:int = (this.initialWidth-layerWidth)/2;
			var layerY:int = (this.initialHeight-layerHeight)/2;
			this.physicalMapLayer1 = new GoogleMapLayerComponent(layerX, layerY, layerWidth, layerHeight, color, GoogleMapLayerComponent.PHYSICAL_MAP_TYPE, this.googleMapObject.getCenter(), this.googleMapObject.getZoom());
			this.addChild(physicalMapLayer1);
		}
		
		public function doClosePhysicalMapLayer():void {
			this.removeChild(this.physicalMapLayer1);
			this.physicalMapLayer1 = null;
		}
		
		public function getPhysicalMapLayer():GoogleMapLayerComponent {
			return this.physicalMapLayer1;
		}
		
		public function doRefreshAllLayers():void {
			var center:LatLng;
			var boundsn:LatLngBounds;
			var centerPoint:Point;
			var centerPointNormalizedToParentRef:Point;
			var newCenter:LatLng;
			for (var i:int = 0; i < this.numChildren; i++) {
				object = this.getChildAt(i);
				if (object is GoogleMapLayerComponent) {
					center = object.getCenter();
					centerPoint = object.localMapToGlobal(object.fromLatLngToViewport(center));
					centerPointNormalizedToParentRef = this.googleMapObject.globalToLocalMap(centerPoint);
					newCenter = this.googleMapObject.fromViewportToLatLng(centerPointNormalizedToParentRef);
					object.setCenter(newCenter);
					object.setZoom(this.googleMapObject.getZoom());
				}
			}
		}
		
		public function refreshLayers(e:MapChangedEvent):void {
			var object:Object;
			if (e.map.getUniqueId() == this.googleMapObject.getUniqueId()) {
				this.doRefreshAllLayers();
			}
		}
		
		public function refreshLayersAfterRotateScaled(e:RotatableScalableChangedEvent):void {
			trace("refreshLayersAfterRotateScaled::1");
			if (e.targetObject == this) {
				trace("refreshLayersAfterRotateScaled::2");
				this.doRefreshAllLayers();
			}
		}
		
		private function showHideMenu(e:MenuButtonChangedStateEvent):void {
			if (e.show) {
				this.menu.alpha = 0;
				this.menu.visible = true;
				Tweener.addTween(this.menu, { alpha:1, time:1.5, transition:"easeOutBack" } );
			} else {
				this.menu.visible = false;
			}
		}
		
	}
}

